/*
 * Copyright (c) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>

#include "securec.h"
#include "hi_debug.h"
#include "hi_str_util.h"

/**
    转换字母为大写.
*/
#define TO_UPPER(c) (((c) >= 'a' && (c) <= 'z') ? ((c) - 'a' + 'A') : (c))

/**
    同strdup.
*/
char* HiStrdup(const char* s)
{
    char *dst = NULL;
    int len;

    len = strlen(s) + 1;
    if (len <= 0) {
        HI_ASSERT(0);
        return NULL;
    }
    dst = malloc(len);
    HI_ASSERT(dst);
    if (memcpy_s(dst, len, s, len) != EOK) {
        HI_ASSERT(0);
    }
    return dst;
}

/**
    不区分大小写的strcmp.
*/
int HiStricmp(const char *s1, const char *s2)
{
    while (TO_UPPER(*s1) == TO_UPPER(*s2) && *s1) {
        s1++;
        s2++;
    }
    return (int)(unsigned char)TO_UPPER(*s1) - (int)(unsigned char)TO_UPPER(*s2);
}

/**
    不区分大小写的strncmp.
*/
int HiStrincmp(const char *s1, const char *s2, size_t n)
{
    while (n > 0 && TO_UPPER(*s1) == TO_UPPER(*s2) && *s1) {
        ++s1;
        ++s2;
        n--;
    }

    if (n == 0) {
        return 0;
    } else {
        return (int)(unsigned char)TO_UPPER(*s1) - (int)(unsigned char)TO_UPPER(*s2);
    }
}

/**
    查找子字符串(不区分大小写).
*/
char* HiStristr(const char *s1, const char *s2)
{
    size_t len2;

    if ((len2 = strlen(s2)) == 0) {
        return (char*)s1;
    }

    for (; *s1; ++s1) {
        if (TO_UPPER(*s1) == TO_UPPER(*s2) && HiStrincmp(s1, s2, len2) == 0) {
            return (char*)s1;
        }
    }
    return NULL;
}

/**
    strxfrm.
*/
int HiStrxfrm(char *s1, const char *s2, int n)
{
    int i;

    n--;
    for (i = 0; i < n && s2[i]; i++) {
        s1[i] = s2[i];
    }
    s1[i] = 0;
    return i;
}

/**
    统计字符串中指定字符出现的次数.
*/
int HiStrchrc(const char* s, int c)
{
    const char *p = s;
    int count = 0;

    while ((p = strchr(p, c)) != NULL) {
        count++;
        p++;
    }
    return count;
}

/**
    strtok线程安全版.
*/
char* HiStrtoks(char** tokensAddr, const char* delimit)
{
    char *tokens = NULL;
    char *p = NULL;
    const char *s = NULL;
    char c;

    if (!*tokensAddr) {
        return NULL;
    }
    tokens = *tokensAddr;

    // 无delimit时，整个tokens作为token返回
    if (!delimit || !*delimit) {
        *tokensAddr = NULL; // 重置token为NULL
        return tokens;
    }

    // 跳过token中的delimit字符
    tokens += strspn(tokens, delimit);
    // 判断是否到尾了
    if (!*tokens) {
        *tokensAddr = NULL; // 重置token为NULL
        return NULL;
    }

    // 找到下一个属于delimit中的字符，并将其置0
    for (p = tokens; (c = *p) != 0; p++) {
        // 判断c是否是delimit中的字符
        for (s = delimit; *s; s++) {
            if (*s == c) {
                *p = 0;
                *tokensAddr = p + 1; // 重置token
                return tokens;
            }
        }
    }

    *tokensAddr = p; // 重置token, *P可能是0
    return tokens;
}

/**
    strtok扩展版.
*/
const char* HiStrtokx(const char** tokensAddr, const char* delimit, int* len)
{
    const char *tokens = NULL;
    const char *p = NULL;
    const char *s = NULL;
    char c;

    if (!*tokensAddr) {
        return NULL;
    }
    tokens = *tokensAddr;

    // 无delimit时，整个tokens作为token返回
    if (!delimit || !*delimit) {
        *tokensAddr = NULL; // 重置token为NULL
        *len = strlen(tokens);
        return tokens;
    }

    // 跳过token中的delimit字符
    tokens += strspn(tokens, delimit);
    // 判断是否到尾了
    if (!*tokens) {
        *tokensAddr = NULL; // 重置token为NULL
        return NULL;
    }

    // 找到下一个属于delimit中的字符，并将其置0
    for (p = tokens; (c = *p) != 0; p++) {
        // 判断c是否是delimit中的字符
        for (s = delimit; *s; s++) {
            if (*s == c) {
                *len = p - tokens; // *len不含分隔符
                *tokensAddr = p + 1; // 重置token
                return tokens;
            }
        }
    }

    *len = p - tokens;
    *tokensAddr = p; // 重置token, *P可能是0
    return tokens;
}

/**
    取path的文件名部分.
*/
const char* HiPathName(const char* path)
{
    HI_ASSERT(path);

    const char *p = strrchr(path, '/');
    if (p) {
        return p + 1;
    }
    return path;
}

/**
    取文件名后缀.
*/
const char* HiPathExt(const char* path)
{
    const char* ext = strrchr(HiPathName(path), '.');
    return ext ? ext + 1 : NULL;
}

